home *** CD-ROM | disk | FTP | other *** search
- %! This is a PostScript library meant to be included in other files %%%
- %% Postscript Code by Jon Monsarrat Copyright 1991
- %% permission given for anything except selling this or deleting the header.
- %%%%%%%%%%% - Approx array %%%%%%%%%%%%%%%%%
- % Approx flattens a path into a series of lines.
- % This new flattened path is returned as a triple-array path representation.
- % The path is broken into sub-paths which have a double-array representation.
- % Each sub-path breaks into vertices which have a single-array representation.
- % Each vertex is of the form X Y. We're doing a fill here so any
- % unclosed subpaths get closed. That's how postscript normally handles fill.
- % It would be easier to use [ X Y ] vertices, but that would waste memory!
- /Approx
- {
- [ [ { /Y exch def /X exch def ] [ X Y }
- { } { } { X Y } pathforall ] ]
- } bind def
-
- %%%%%%%%%%%%%%%%%%% array num bool SortArray array %%%%%%%%%%%%%%%
- % SortArray bubble sorts "array" of packets in increasing order, packets are
- % groups of numbers and a packet is of size "num". Sorting is done based
- % on the value of the first item in each packet. When sorting is done,
- % SortArray goes through and deletes all equal packets if "bool" is true.
- /SortArray
- {
- 10 dict begin
- /DelEquals exch def /Pack exch def
- /newlist exch def
- 0 Pack newlist length 2 Pack mul sub
- {
- /anum exch def
- anum Pack add Pack newlist length 1 Pack mul sub
- {
- /bnum exch def
- newlist anum get newlist bnum get ge
- {
- /flag true def
- newlist anum get newlist bnum get eq Pack 2 eq and
- {
- /flag false def
- newlist anum 1 add get newlist bnum 1 add get add 0 eq
- {
- newlist anum 1 add get 1 eq ontop xor { /flag true def } if
- } if
- } if
- flag
- {
- 0 1 Pack 1 sub
- {
- /ind exch def
- /temp newlist anum ind add get def
- newlist anum ind add newlist bnum ind add get put
- newlist bnum ind add temp put
- } for
- } if
- } if
- } for
- } for
-
- DelEquals % if this boolean is true, delete all equal packs
- {
- [
- 0 Pack newlist length 2 Pack mul sub
- {
- /anum exch def
- newlist anum get newlist anum Pack add get ne
- {
- 0 1 Pack 1 sub
- {
- anum add newlist exch get
- } for
- } if
- } for
- 0 1 Pack 1 sub
- {
- /ind exch def
- newlist newlist length Pack sub ind add get
- } for
- ]
- }
- {
- newlist
- } ifelse
- end % temp dict 10
- } bind def
-
- %%%%%%%%%%%%%%%%%% bool CheeseY X1 W1 or nothing %%%%%%%%%%
- % CheeseY uses defined variables Y1 (a number), oldx, oldy, newx, newy.
- % CheeseY asks "does the line segment bounded by oldxy, newxy cross y=Y1?
- % If so, CheeseY leaves X1 W on the stack, where (X1,Y1) is the point of
- % intersection. The winding value W is calculated from the sign of the slope.
- % CheeseY takes one argument which is a boolean value. This boolean is
- % true is the Y1 value is "on top" of the region of interest, false if "below".
- % This is to deal correctly with line segments which end on the y=Y1 line.
- % These special line segments are ignored if they don't pass through the
- % region of interest. It would be easier to use [ X W ] but memory wasteful.
- /CheeseY
- {
- /top exch def
- oldy newy 2 copy gt { exch } if
- Y1 ge exch Y1 le and
- {
- oldy newy ne
- {
- oldx newx sub oldy newy sub div
- oldy Y1 sub mul oldx exch sub
- oldy newy lt { 1 } { -1 } ifelse
- }
- {
- newx 0
- } ifelse
-
- % If the line segment does NOT go through region of interest
- % but rather just happens to end on line y=Y1, don't use it.
- oldy Y1 eq
- {
- dup top { -1 } { 1 } ifelse ne { pop pop } if
- }
- {
- newy Y1 eq
- {
- dup top { 1 } { -1 } ifelse ne { pop pop } if
- } if
- } ifelse
- } if
- } bind def
-
- %%%%%%%%%%%%%%%%%%%%% array num bool CheeseWhiz array %%%%%%%%%%%%%%%%%
- % CheeseWhiz traverses the flattened path as computed by Approx to find
- % any points of intersection with the line y=Y1, where Y1 is it's num argument.
- % It's boolean argument is true if y=Y1 bounds the region of interest "on top".
- % For all points of intersection X1 goes on the stack, where [ X1 Y1 ]
- % is the point, BUT ONLY IF the winding value or evenodd calculation says
- % to. The winding value is complex and calculated from the sign of the slope.
- % CheeseWhiz does this by breaking the path into line segments and passing
- % it to CheeseY. The final array of X1 values is sorted, keeping duplicates.
- /CheeseWhiz
- {
- 15 dict begin
- /ontop exch def
- /Y1 exch def
- [ exch
- {
- /oldx (Begin) def
- /flag false def
- {
- flag
- {
- /newy exch def
- oldx (Begin) eq
- { /firstx newx def /firsty newy def} { ontop CheeseY } ifelse
- /oldx newx def /oldy newy def
- }
- {
- /newx exch def
- } ifelse
- /flag flag not def
- } forall
- oldx (Begin) ne
- {
- /newx firstx def % Even if the subpath is not closed, PostScript
- /newy firsty def % fill methodology says close it. So wrap around.
- ontop CheeseY
- } if
- } forall
- ]
- % Sort the array of X W values
- 2 false SortArray
- % Now go through and take out X's where there is no inside/outside change
- [ exch
- fillout { LM exch } if
- /winding 0 def
- /inside false def % always start off outside
- /flag false def
- {
- flag
- {
- winding add /winding exch def
- evenodd not
- {
- winding 0 eq inside xor
- { pop } { /inside inside not def } ifelse
- } if
- } if
- /flag flag not def
- } forall
- fillout { RM } if
- ]
- end % temp dict 15
- } def
- %% End of PostScript Path-breaking Library
-